#include "teclado/teclado.h"

#include "evento/gerenciador.h"
#include "tarefa/gerenciador.h"
#include "teclado/evento_teclado.h"

#include <utility>

namespace teclado {

iterator_evento teclado::cadastra_aperta(SDLKey key, evento::tratador* funcao) {
  return mapa_aperta_.insert(std::make_pair(key, funcao));
}

iterator_tarefa teclado::cadastra_baixo(SDLKey key, tarefa::tarefa* funcao) {
  return mapa_baixo_.insert(std::make_pair(key, funcao));
}

iterator_evento teclado::cadastra_solta(SDLKey key, evento::tratador* funcao) {
  return mapa_solta_.insert(std::make_pair(key, funcao));
}

iterator_tarefa teclado::get_baixo(SDLKey tipo) {
    return mapa_baixo_.find(tipo);
}

void teclado::retira_baixo(iterator_tarefa it) {
    mapa_baixo_.erase(it);
}

iterator_evento teclado::get_aperta(SDLKey tipo) {
    return mapa_aperta_.find(tipo);
}
void teclado::retira_aperta(iterator_evento it) {
    mapa_aperta_.erase(it);
}

iterator_evento teclado::get_solta(SDLKey tipo) {
    return mapa_solta_.find(tipo);
}
void teclado::retira_solta(iterator_evento it) {
    mapa_solta_.erase(it);
}

void teclado::invoca(const evento::evento& event, int passou) {
  const evento_teclado& tec = *reinterpret_cast<const evento_teclado*>(&event);
  iterator_evento it;
  if (tec.tipo() == evento::TECLA_APERTADA) {
    it = mapa_aperta_.find(tec.tecla_);
    for (;it != mapa_aperta_.end() && it->first == tec.tecla_; it++)
      it->second->invoca(event, passou);
    abaixados_.insert(tec.tecla_);
  } else if (tec.tipo() == evento::TECLA_SOLTA) {
    it = mapa_solta_.find(tec.tecla_);
    for (;it != mapa_solta_.end() && it->first == tec.tecla_; it++)
      it->second->invoca(event, passou);
    abaixados_.erase(tec.tecla_);
  }
}
bool teclado::executa(int passou) {
  iterator_tarefa it;
  for (std::set<SDLKey>::iterator it2 = abaixados_.begin();
     it2 != abaixados_.end();
     it2++ ) {
    it = mapa_baixo_.find(*it2);
    for (;it != mapa_baixo_.end() && it->first == *it2; it++)
      it->second->executa(passou);
  }
    return true;
}

teclado::~teclado() {
  std::map<SDLKey, evento::tratador*>::iterator it;
  for (it = mapa_solta_.begin(); it != mapa_solta_.end(); it++)
    if (it->second->deleta_)
      delete it->second;
  for (it = mapa_aperta_.begin(); it != mapa_aperta_.end(); it++)
    if (it->second->deleta_)
      delete it->second;
  std::map<SDLKey, tarefa::tarefa*>::iterator it2;
  for (it2 = mapa_baixo_.begin(); it2 != mapa_baixo_.end(); it2++)
    if (it2->second->deleta_)
      delete it2->second;
}

teclado::teclado() {
  GE.cadastra(evento::TECLA_APERTADA, this);
  GE.cadastra(evento::TECLA_SOLTA, this);
  GT.cadastra(this);
}

}
